/*
 * Copyright (c) 2007
 *	Alberto Magni, Maggioni Marcello
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.*/
package servlets;
import Database.AddressesDB;
import Database.ConfigurationDB;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import beans.*;
import emailsender.MailAuthenticator;
import exceptions.ConfigurationException;
import exceptions.DatabaseException;
import exceptions.IncorrectFileTypeException;
import java.util.*;
import javax.activation.DataHandler;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import org.apache.tomcat.util.http.fileupload.*;
import parser.Parser;
import spamassassin.SpamAssassinInterface;
/**BridgeSrv check the parameters passed by the user, prepare the connection with the
 * mail-server and set up the message.
 * If an error is reveald an exception is throw and the excecution passes to a jsp that
 * notifies the error to the user.
 @author Alberto Magni*/
public class BridgeSrv extends HttpServlet 
{
    
    private ConfigurationDB cdb; 
    private AddressesDB adb;
//------------------------------------------------------------------------------
    @Override
    public void init() throws ServletException  
    {
        super.init();
        cdb = (ConfigurationDB) this.getServletContext().getAttribute("configurationdb");
        adb = (AddressesDB) this.getServletContext().getAttribute("addressesdb");
    }
//------------------------------------------------------------------------------
    @Override
    @SuppressWarnings("unchecked")
    /**Handles the HTTP POST method. Here are checked the parameters passed by the user and the message
     * is prepared.
    * @param request servlet request
    * @param response servlet response
      @throws ServletException
      @throws IOException*/
    protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException 
    {   
        Parser parser = new Parser();
        LoginBean lb = (LoginBean) request.getSession().getAttribute("loggedin");
        String text=null;
        String from=null;
        String text_type=null;
        String [] to_list=null;
        String to_file_path=null;
        String subject=null;
        String password=null;
        String file_to_send=null;
        DiskFileUpload dfu = new DiskFileUpload();
        List<FileItem> items =null;
        //get all the insered parameters of the user
        try
        {
            items = (List<FileItem>) dfu.parseRequest(request);
        }
        catch(Exception exception)
        {
            request.setAttribute("exception",exception);
            request.getRequestDispatcher("error.jsp").forward(request, response); 
            return;
        }
        //get the all the single parameters of the user
        for(FileItem item:items)
        {
            if(item.getFieldName().equals("from"))
            {
                //the from address
                from=new String(item.getString());
            }
            if(item.getFieldName().equals("to"))
            {
                //path of the file with the addresses of the recipients
                to_file_path=new String(item.getName());
            }
            if(item.getFieldName().equals("fileoftext"))
            {
                //name of the file with the text to send
                file_to_send=new String(item.getName());
            }
            if(item.getFieldName().equals("password"))
            {
                password=new String(item.getString());
            }
            if(item.getFieldName().equals("subject"))
            {
                subject=new String(item.getString());
            }
        }
        //if the "From:" field is empty ...
        if(from.equals(""))
        {
            Exception exception=new Exception("The field \"From:\" is empty !");
            request.setAttribute("exception",exception);
            request.getRequestDispatcher("error.jsp").forward(request, response);
            return;
        }
        try
        {
            //get the dafault list of recipients
            to_list=adb.getAddresses(lb.getUsername());
        }
        catch(DatabaseException exception)
        {
            request.setAttribute("exception",exception);
            request.getRequestDispatcher("error.jsp").forward(request, response);
            return;
        }
        if((to_list==null&&to_file_path==null)||to_list==null&&to_file_path.equals(""))
        {
            Exception exception=new Exception("The field \"To:\" is empty !");
            request.setAttribute("exception",exception);
            request.getRequestDispatcher("error.jsp").forward(request, response);
            return;
        }
        for(FileItem item:items)
        { 
            if(item.getFieldName().equals("to"))
            {
                if(!to_file_path.equals("")&&(to_file_path!=null))
                {
                    try
                    {
                        //get the addresses of the recipients
                        to_list=parser.getAddresses(item);
                    }
                    catch(Exception exception)
                    {
                        request.setAttribute("exception",exception);
                        request.getRequestDispatcher("error.jsp").forward(request, response);
                        return;
                    }
                }
            }
            if(item.getFieldName().equals("fileoftext"))
            {
                if(file_to_send.equals(""))
                {
                    text="";
                    text_type="text/plain";
                }
                else
                {
                    //if the text file is not of the required format...
                    if(!item.getContentType().equals("text/plain")&&!item.getContentType().equals("text/html"))
                    {
                        IncorrectFileTypeException exception = new IncorrectFileTypeException("The \"File:\" file must be: .txt or .html");    
                        request.setAttribute("exception",exception);
                        request.getRequestDispatcher("error.jsp").forward(request, response); 
                        return;
                    }
                    else
                    {
                        text=item.getString();
                        //get the tipe of the text file
                        text_type=item.getContentType();       
                    }
                }
            }      
        }
        //get the list of the attachments
        ArrayList<FileItem> item_list = new ArrayList<FileItem>();
        int counter=0;
        for(int index=0;index<items.size();index++)
        {
            if(items.get(index).getFieldName().startsWith("file_")&&!items.get(index).getString().equals("")&&!items.get(index).getName().equals(""))
            {
                item_list.add(items.get(index));
                counter++;
            }
        }
        //set all the fields of the Bean
        UserDataBean udb =new UserDataBean();
        if(counter==0)
        {
            udb.setItems(null);
        }
        else
        {
            FileItem [] items_array=new FileItem [counter];
            udb.setItems(item_list.toArray(items_array));
        }
        udb.setText(text);
        udb.setFrom(from);
        udb.setTextType(text_type);
        udb.setPassword(password);
        udb.setSubject(subject);
        udb.setRecipients(to_list);
        MailBean mb=null;
        try
        {
            //get the addresses of the recipients
            mb=setMessage(udb, lb);
        }
        catch(Exception exception)
        {
            request.setAttribute("exception",exception);
            request.getRequestDispatcher("error.jsp").forward(request, response);
            return;
        }
        //redirect to the jsp page
        request.getSession().setAttribute("maildatabase",mb);
        response.sendRedirect("recipients.jsp");
    }
//------------------------------------------------------------------------------    
    /**Prepare the message 
     * @param udb contains all the parameters usefull to write the message
       @return the parameters to send the mail
       @throws Exception if an internal error eccours*/
    /*private MailBean setMessage(UserDataBean udb, LoginBean lb) throws Exception
    {
        MailBean mb = new MailBean();
        String from=udb.getFrom();
        String password=udb.getPassword();
        String subject = udb.getSubject();
        String text=udb.getText();
        String text_type=udb.getTextType();
        FileItem items [] = udb.getItems();
        String recipients [] = udb.getRecipients();
        String server = cdb.getServer(lb.getUsername());
        boolean srvauth;
        if (!lb.isAdmin())
            srvauth = cdb.getServerAuthMode(lb.getUsername());
        else
            srvauth = cdb.getServerAuthMode(null);
        
        if (server == null)
            server = cdb.getServer(null);
        if (server == null)
            throw new ConfigurationException("The SMTP server address hasn't been configured. Please check your configuration page.");
        Properties properties=new Properties();
        properties.put("mail.smtp.host",server);
        Session session = null;
        if (srvauth) {
            properties.put("mail.smtp.auth", "true");
            properties.put("mail.smtp.starttls.enable", "true");
            MailAuthenticator authenticator = new MailAuthenticator(from, password);
            session = Session.getInstance(properties, authenticator);
        } else {
            session = Session.getInstance(properties);
        }
        Transport transport=null;
        try
        {
            transport=session.getTransport("smtp");
            transport.connect();
        }
        catch(MessagingException exception)
        {
            throw new AuthenticationFailedException("your password may be wrong or the mail server is not correct !");
        }
        MimeMessage message=new MimeMessage(session);
        message.setSubject(subject);
        message.setFrom(new InternetAddress(from));
        BodyPart part = new MimeBodyPart();
        part.setContent(text, text_type);
        MimeMultipart multipart = new MimeMultipart();
        multipart.addBodyPart(part);
        //attachments
        if(items!=null)
        {
            for(int index=0;index<items.length;index++)
            {
                part = new MimeBodyPart();
                ByteArrayDataSource bads=new ByteArrayDataSource(items[index].getInputStream(),items[index].getContentType());
                part.setDataHandler(new DataHandler(bads));
                String name=items[index].getName();
                String[] path_parts;
                String line_feed = System.getProperty("file.separator");
                path_parts = name.split(line_feed);
                part.setFileName(path_parts[path_parts.length-1]);
                multipart.addBodyPart(part);
            }
        }
        message.setContent(multipart);
        SpamAssassinInterface sai=new SpamAssassinInterface();
        String table =null;
        Float [] parameters=new Float[2];
        parameters[0]=null;
        parameters[1]=null;
        if(cdb.getSpamCheck(null))
        {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            message.writeTo(baos);
            sai.callSpamAssassin(baos.toByteArray());
            parameters=sai.getSpamRating();
            table=sai.getCriticalElementsTable();
            mb.setRate(parameters[0]);
            mb.setLimit(parameters[1]);
        }
        mb.setTable(table);
        mb.setMessage(message);
        mb.setRecipients(recipients);
        mb.setTransport(transport);
        return mb;
    }*/
    private MailBean setMessage(UserDataBean udb, LoginBean lb) throws Exception
    {
        MailBean mb = new MailBean();
        String from=udb.getFrom();
        String password=udb.getPassword();
        String subject = udb.getSubject();
        String text=udb.getText();
        String text_type=udb.getTextType();
        FileItem items [] = udb.getItems();
        String recipients [] = udb.getRecipients();
        String server = cdb.getServer(lb.getUsername());
        boolean srvauth;
        if (!lb.isAdmin())
            srvauth = cdb.getServerAuthMode(lb.getUsername());
        else
            srvauth = cdb.getServerAuthMode(null);
        
        if (server == null)
            server = cdb.getServer(null);
        if (server == null)
            throw new ConfigurationException("The SMTP server address hasn't been configured. Please check your configuration page.");
        Properties properties=new Properties();
        properties.put("mail.smtp.host",server);
        Session session = null;
        if (srvauth) {
            properties.put("mail.smtp.auth", "true");
            properties.put("mail.smtp.starttls.enable", "true");
            MailAuthenticator authenticator = new MailAuthenticator(from, password);
            session = Session.getInstance(properties, authenticator);
        } else {
            session = Session.getInstance(properties);
        }
        Transport transport=null;
        try
        {
            transport=session.getTransport("smtp");
            transport.connect();
        }
        catch(MessagingException exception)
        {
            throw new AuthenticationFailedException("your password may be wrong or the mail server is not correct !");
        }
        MimeMessage message=new MimeMessage(session);
        message.setSubject(subject);
        message.setFrom(new InternetAddress(from));
        if(items!=null)
        {
            BodyPart part = new MimeBodyPart();
            part.setContent(text, text_type);
            MimeMultipart multipart = new MimeMultipart();
            multipart.addBodyPart(part);
            for(int index=0;index<items.length;index++)
            {
                part = new MimeBodyPart();
                ByteArrayDataSource bads=new ByteArrayDataSource(items[index].getInputStream(),items[index].getContentType());
                part.setDataHandler(new DataHandler(bads));
                String name=items[index].getName();
                String[] path_parts;
                String line_feed = System.getProperty("file.separator");
                path_parts = name.split(line_feed);
                part.setFileName(path_parts[path_parts.length-1]);
                multipart.addBodyPart(part);
                message.setContent(multipart);
            }
            
        }
        else
        {
            message.setText(text);
        }
        SpamAssassinInterface sai=new SpamAssassinInterface();
        String table =null;
        Float [] parameters=new Float[2];
        parameters[0]=null;
        parameters[1]=null;
        if(cdb.getSpamCheck(null))
        {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            message.writeTo(baos);
            sai.callSpamAssassin(baos.toByteArray());
            parameters=sai.getSpamRating();
            table=sai.getCriticalElementsTable();
            mb.setRate(parameters[0]);
            mb.setLimit(parameters[1]);
        }
        mb.setTable(table);
        mb.setMessage(message);
        mb.setRecipients(recipients);
        mb.setTransport(transport);
        return mb;
    }
}
